package lk.icta.user.web.action;

import lk.icta.common.AppConstants;
import lk.icta.common.dao.BranchDAO;
import lk.icta.common.dao.DSDivisionDAO;
import lk.icta.common.dao.DistrictDAO;
import lk.icta.common.dao.ProvinceDAO;
import lk.icta.common.entity.Branch;
import lk.icta.common.entity.DSDivision;
//import lk.icta.common.entity.Province;
import lk.icta.common.entity.District;
import lk.icta.common.service.MailSenderService;
//import lk.icta.common.util.MailUtil;
import lk.icta.common.service.SmsSenderService;
import lk.icta.common.web.WebConstants;
import lk.icta.common.web.action.BaseAction;
import lk.icta.user.common.ErrorCodes;
import lk.icta.user.common.UserRuntimeException;
import lk.icta.user.dao.RoleDAO;
import lk.icta.user.dao.UserDAO;
import lk.icta.user.entity.Role;
import lk.icta.user.entity.User;
import lk.icta.user.service.UserManager;
import org.apache.struts2.interceptor.SessionAware;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;
import java.util.regex.Pattern;

import lk.icta.core.entity.LandApplication;
import lk.icta.core.dao.LandApplicationDAO;

/**
 * @author Duminda Dharmakeerthi
 * @author Supun Nimesh Karunathilaka
 * @author Sisiruwan Senadeera
 */
public class UserAction extends BaseAction implements SessionAware {
    private static final Logger logger = LoggerFactory.getLogger(UserAction.class);

    private final UserManager userManager;
    private String slcUserName;
    private User registerUser;
    private Map<String, String> roleListByRoleId;
    private Map<Integer, String> provinceList;
    private Map<Integer, String> branchList;
    private Map<Integer, String> districtList;
    private Map<Integer, String> dsDivisionList;
    private Map<Integer, String> dsDivisionsSelectedList;
    private Map<String, String> userRolesSelectedList;
    private int[] dsDivisionsSelected;
    private String[] userRolesSelected;
    private Set<String> roleSet;
    private RoleDAO roleDAO;
    private UserDAO userDAO;
    private ProvinceDAO provinceDAO;
    private BranchDAO branchDAO;
    private DistrictDAO districtDAO;
    private DSDivisionDAO dsDivisionDAO;
    private LandApplicationDAO landApplicationDAO;
    private String password;
    private String newPassword;
    private String retypePassword;
    private String username;
    private List<User> userList;
    private List<LandApplication> slcLandApplicationsList;
    private User.State[] state;
    private User.State stateId;
    private String prefLanguage;
    private String userId;
    private String roleId;
    private int editMode;
    private int dsDivision;
    private int district;
    private int province;
    private int branch;
    private int searchMode;
    private int[] assignedDistricts;
    private final MailSenderService mailSenderService;
    private final SmsSenderService smsSenderService;

    private Pattern pattern;
    private static final String PASSWORD_PATTERN =
            "(?=^.{6,}$)((?=.*\\d)|(?=.*\\W+))(?![.\\n])(?=.*[A-Z])(?=.*[a-z]).*$";

    public UserAction(UserManager userManager, RoleDAO roleDAO, UserDAO userDAO,
                      DistrictDAO districtDAO, DSDivisionDAO dsDivisionDAO,
                      MailSenderService mailSenderService, ProvinceDAO provinceDAO, LandApplicationDAO landApplicationDAO, SmsSenderService smsSenderService,
                      BranchDAO branchDAO) {
        this.userManager = userManager;
        this.roleDAO = roleDAO;
        this.userDAO = userDAO;
        this.districtDAO = districtDAO;
        this.dsDivisionDAO = dsDivisionDAO;
        this.mailSenderService = mailSenderService;
        this.provinceDAO = provinceDAO;
        this.landApplicationDAO = landApplicationDAO;
        this.smsSenderService = smsSenderService;
        this.branchDAO = branchDAO;
    }

    private void populateBasicLists() {
        //todo: refactore this code
        logger.debug("Populate Basic Lists [user name: {}]", getUser().getUsername());
        if (AppConstants.PA_USER_ROLE.equals(user.getRole().getId())) {
            populatePABasicLists();
        } else {
            roleListByRoleId = roleDAO.getRoleList();

            if (slcUserName == null) {
                slcUserName = roleListByRoleId.get(AppConstants.SLC_USER_ROLE);
            }

            if (searchMode != 1) {
                roleListByRoleId.remove(AppConstants.SLC_USER_ROLE);
            } else {
                roleListByRoleId.put(AppConstants.SLC_USER_ROLE, slcUserName);
            }

            roleSet = roleListByRoleId.keySet();

            //roleSet.remove("SLC");
            username = user.getUsername();
            //userList = userDAO.getAllUsers();//todo: omit default users admin, orlp, lcg
            userList = new ArrayList<User>();

            state = User.State.values();
            stateId = User.State.ACTIVE;
            prefLanguage = user.getPrefLanguage();
            provinceList = provinceDAO.getProvinceList(language);
            branchList = branchDAO.getBranchList(language);
            //  districtList = districtDAO.getAllDistrictNamesByProvinceId(1, language, user);
            districtList = districtDAO.getAllDistrictNames(language, user);
            dsDivisionList = dsDivisionDAO.getDSDivisionNamesByDistrictId(1, language, user);
            //dsDivisionList = dsDivisionDAO.getDSDivisionNamesByDistrictId(1, language, user);
            dsDivisionsSelectedList = new HashMap<Integer, String>();
            userRolesSelectedList = new HashMap<String, String>();
        }

    }

    private void populatePABasicLists() {
        logger.debug("Populate PA Basic Lists [user name: {}]", getUser().getUsername());
        // roleListByRoleId = roleDAO.getRoleList();
        roleListByRoleId = new HashMap<String, String>();

        Role role = roleDAO.getRole(AppConstants.ORLM_USER_ROLE);
        roleListByRoleId.put(role.getId(), role.getName());

        role = roleDAO.getRole(AppConstants.ORDS_USER_ROLE);
        roleListByRoleId.put(role.getId(), role.getName());

        role = roleDAO.getRole(AppConstants.LO_USER_ROLE);
        roleListByRoleId.put(role.getId(), role.getName());

        role = roleDAO.getRole(AppConstants.PA_USER_ROLE);
        roleListByRoleId.put(role.getId(), role.getName());

        if (slcUserName == null) {
            slcUserName = roleListByRoleId.get(AppConstants.SLC_USER_ROLE);
        }

        if (searchMode != 1) {
            roleListByRoleId.remove(AppConstants.SLC_USER_ROLE);
        } else {
            roleListByRoleId.put(AppConstants.SLC_USER_ROLE, slcUserName);
        }

        /*roleListByRoleId.remove(AppConstants.ORRFL_USER_ROLE);
        roleListByRoleId.remove(AppConstants.ORLP_USER_ROLE);
        roleListByRoleId.remove(AppConstants.ADMIN_USER_ROLE);
        roleListByRoleId.remove(AppConstants.PLC_USER_ROLE);
        roleListByRoleId.remove(AppConstants.LCG_USER_ROLE);
        roleListByRoleId.remove(AppConstants.ORMOI_USER_ROLE);
        roleListByRoleId.remove(AppConstants.SLC_USER_ROLE);
        roleListByRoleId.remove(AppConstants.PA_USER_ROLE);*/

        roleSet = roleListByRoleId.keySet();

        username = user.getUsername();
        // userList = userDAO.getAllUsersByDS(userDsId,user);
        userList = new ArrayList<User>();
        state = User.State.values();
        stateId = User.State.ACTIVE;
        prefLanguage = user.getPrefLanguage();

        provinceList = new HashMap<Integer, String>();
        provinceList.put(userProvinceId, provinceDAO.getProvinceById(userProvinceId).getEnProvinceName());

        /*districtList = districtDAO.getAllDistrictNamesByProvinceId(userProvinceId, language, user);
        dsDivisionList = dsDivisionDAO.getDSDivisionNamesByDistrictId(userProvinceId, language, user);*/

        districtList = new HashMap<Integer, String>();
        dsDivisionList = new HashMap<Integer, String>();

        dsDivisionsSelectedList = new HashMap<Integer, String>();
        userRolesSelectedList = new HashMap<String, String>();

    }

    public String pageLoad() {
        populateBasicLists();
        return SUCCESS;
    }

    /*public String pageLoadUpdateUsers() {
        populateUpdateUsersList();
        return SUCCESS;
    }*/

    //Check whether the user is DS level user
    public boolean isDSUser() {
        if (AppConstants.ORLM_USER_ROLE.equals(roleId) ||
                AppConstants.ORDS_USER_ROLE.equals(roleId) ||
                AppConstants.LO_USER_ROLE.equals(roleId)) {
            return true;
        }
        return false;

    }

    //Check whether the user is District Branch level
    public boolean isBranchUser() {
        if (AppConstants.SC_USER_ROLE.equals(roleId)) {
            return true;
        }
        return false;

    }

    public boolean isBranchHead() {
        if (AppConstants.BO_USER_ROLE.equals(roleId) || AppConstants.SH_USER_ROLE.equals(roleId)) {
            return true;
        }
        return false;

    }

    public boolean isDepartmentUser() {
        if (AppConstants.SDH_USER_ROLE.equals(roleId) || AppConstants.DH_USER_ROLE.equals(roleId)) {
            return true;
        }
        return false;

    }

    private boolean isPLCUSer() {
        if (AppConstants.PLC_USER_ROLE.equals(roleId) ||
                AppConstants.ORRFL_USER_ROLE.equals(roleId) ||
                AppConstants.PMA_USER_ROLE.equals(roleId) ||
                AppConstants.APLC_USER_ROLE.equals(roleId) ||
                AppConstants.DPLC_USER_ROLE.equals(roleId) ||
                AppConstants.PA_USER_ROLE.equals(roleId)) {
            return true;
        }
        return false;
    }

    //user edit page load
    public String initUpdateUser() {
        try {
            editMode = 1;
            populateBasicLists();
            //populateUpdateUsersList();
            setUserRolesSelectedList();
            registerUser = userDAO.getUserByUserName(userId);
            logger.debug("initupdateUser mobile: {}", registerUser.getDsDivisions().size());
            roleId = registerUser.getRole().getId();
            stateId = registerUser.getStatus();
            //setDsDivisionsSelectedList();
            setDistrictsSelectedList();


        } catch (Exception e) {
            e.printStackTrace();
        }
        return SUCCESS;
    }

    public String createUser() {
        logger.debug("Attempt to create user :{}", registerUser.getUsername());
        populateBasicLists();
        try {

            logger.debug("The user name who is going to be created is : {}", registerUser.getUsername());
            User existingUser = userManager.getUserByUserName(registerUser.getUsername());
            if (existingUser != null) {
                addActionMessage(getText("user_name_already_exists.label"));
            }

            User currentUser = getUser();
            String pass = getRandomPassword(getRandomInteger());
            //set default password
            //pass = "password";
            //egisterUser.setDsDivisions(populateDSDivisions());
            //for eRail
            registerUser.setDistricts(populateDistricts());
            registerUser.setBranch(populateBranch());


            registerUser.setRoles(populateUserRoles());
            if (hasActionErrors()) {
                return ERROR;
            }
            userManager.createUser(registerUser, currentUser, roleId, pass);
            addActionMessage(getText("user_created_successfully.label") + " " + getText("password_of_the_user_is.label") + " " + pass);

            sendMail(registerUser.getEmail(), registerUser.getUsername(), pass);

            String message = "You have successfully registered into eSLIMS\nYour Username : " + registerUser.getUsername() + "\nGenerated Password is : " + pass + "\nPlease log and change your password\n\nhttp://eslims.gov.lk";
            smsSenderService.sendSMS(message, registerUser.getMobile());

            /*registerUser.setUsername("");
            registerUser.setFullName("");
            registerUser.setEmail("");*/

            registerUser = null;

            return SUCCESS;
        } catch (UserRuntimeException e) {
            switch (e.getErrorCode()) {
                case ErrorCodes.ENTITY_ALREADY_EXIST:
                    addActionError(getText("unable_to_register_user.label") + " " + getText("user_already_assigned.label"));
                    break;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return ERROR;
    }

    public String changePassword() {
        logger.info("requesting a password change.......");
        String hashPassword = userManager.hashPassword(password);

        //Check password Strong
        //if (!validatePassword(newPassword)) {
        if (!validateSimplePassword(newPassword)) {
            username = getUser().getUsername();
            addActionError(getText("password_not_strong.label"));

            if (AppConstants.SLC_USER_ROLE.equals(getUser().getRole().getId())) {
                return "applicantError";
            }

            if (AppConstants.ANDROID.equals(getUser().getUserDevice())) {
                return "mobileError";
            }

            return ERROR;
        }

        if (getUser().getPasswordHash().equals(userManager.hashPassword(hashPassword))) {

            if (getUser().getLoginState() != User.LoginState.NORMAL) {
                getUser().setLoginState(User.LoginState.NORMAL);
            }
            userManager.updatePassword(userManager.hashPassword(newPassword), getUser());
            addActionMessage(getText("password_changed_successfully.label"));

            if (AppConstants.SLC_USER_ROLE.equals(getUser().getRole().getId())) {
                return "applicantSuccess";
            }

            logger.debug("user device .... {}", getUser().getUserDevice());
            if (AppConstants.ANDROID.equals(getUser().getUserDevice())) {
                return "mobileSuccess";
            }
            //for department user
            return SUCCESS;
        } else {
            username = getUser().getUsername();
            addActionError(getText("pls_enter_correct_password.label"));

            if (AppConstants.SLC_USER_ROLE.equals(getUser().getRole().getId())) {
                return "applicantError";
            }

            if (AppConstants.ANDROID.equals(getUser().getUserDevice())) {
                return "mobileError";
            }
            return ERROR;
        }
    }

    public String resetPassword() {
        logger.info("requesting a password reset .......");

        try {
            //String resetPassword = "password";
            String resetPassword = getRandomPassword(getRandomInteger());
            User currentUser = userDAO.getUserByUserName(registerUser.getUsername());

            //currentUser.setFirstLogin(true);
            currentUser.setLoginState(User.LoginState.PASSWORD_RESET);
            currentUser.getLifeCycleInfo().setLastUpdatedUser(user);
            currentUser.getLifeCycleInfo().setLastUpdatedTimeStamp(new Date());
            userManager.updatePassword(userManager.hashPassword(resetPassword), currentUser);

            if ((currentUser != null) && (currentUser.getEmail() != null && currentUser.getEmail().isEmpty() == false)) {
                sendMail(currentUser.getEmail(), currentUser.getUsername(), resetPassword);
            }
            addActionMessage(getText("password_reset_successfully.label") + " " + getText("resetted_password_is.label") + "  " + resetPassword);

            return SUCCESS;
        } catch (Exception ex) {
            ex.printStackTrace();
            return ERROR;
        }
    }

    public String updateUser() {
        logger.debug("Attempt to update user:{}", registerUser.getUsername());

        try {
            logger.debug("Attempt to update user:{}", registerUser.getUsername());
            User currentUser = userDAO.getUserByUserName(registerUser.getUsername());
            currentUser.setFullName(registerUser.getFullName());
            currentUser.setEmail(registerUser.getEmail());
            currentUser.setMobile(registerUser.getMobile());
            currentUser.setStatus(stateId);

            if (currentUser.getLoginState() == User.LoginState.FIRST_LOGIN) {
                currentUser.setRole(roleDAO.getRole(roleId));
                //currentUser.setDsDivisions(populateDSDivisions());
                currentUser.setRoles(populateUserRoles());

            } else {
                roleId = currentUser.getRole().getId();
                currentUser.setRole(roleDAO.getRole(roleId));
                //currentUser.setDsDivisions(currentUser.getDsDivisions());
                currentUser.setRoles(currentUser.getRoles());
            }

            //currentUser.setDsDivisions(populateDSDivisions());
            currentUser.setDistricts(populateDistricts());
            currentUser.setBranch(populateBranch());

            if (!hasActionErrors()) {
                userManager.updateUser(currentUser, getUser());
                addActionMessage(getText("user_updated_successfully.label"));
                populateBasicLists();
                //populateUpdateUsersList();
                return SUCCESS;
            } else {
                return initUpdateUser();
            }

        } catch (UserRuntimeException e) {
            e.printStackTrace();
            return ERROR;
        } catch (Exception e) {
            e.printStackTrace();
            return ERROR;
        }
    }

    private boolean validatePassword(final String password) {
        pattern = Pattern.compile(PASSWORD_PATTERN);
        return pattern.matcher(password).matches();
    }

    private boolean validateSimplePassword(final String password) {
        return (password.length() >= 6 ? true : false);
    }


    public String changePreferredLanguage() {
        session.put(WebConstants.SESSION_USER_LANG, new Locale(prefLanguage,
                AppConstants.COUNTRY));
        userManager.updatePreferredLanguage(prefLanguage, user);
        addActionMessage(getText("pref_language_changed_successfully.label"));
        return SUCCESS;
    }

    private void setDsDivisionsSelectedList() {
        Set<DSDivision> dsDivisionSelectedList = userDAO.getUserByUserName(userId).getDsDivisions();

        if (dsDivisionSelectedList != null && dsDivisionSelectedList.size() != 0) {
            if (dsDivisionSelectedList.size() == 1 && isDSUser()) {
                dsDivision = dsDivisionSelectedList.iterator().next().getId();
                district = dsDivisionSelectedList.iterator().next().getDistrict().getId();
                province = dsDivisionSelectedList.iterator().next().getDistrict().getProvince().getId();

                districtList = districtDAO.getAllDistrictNamesByProvinceId(province, language, user); //western province
                dsDivisionList = dsDivisionDAO.getDSDivisionNamesByDistrictId(district, language, user);
            } else {
                dsDivisionsSelectedList = new HashMap<Integer, String>();
                for (DSDivision ds : dsDivisionSelectedList) {
                    String val = Long.toString(ds.getCode());
                    if (AppConstants.ENGLISH.equals(language)) {
                        val = ds.getEnDivisionName();
                    } else if (AppConstants.SINHALA.equals(language)) {
                        val = ds.getSiDivisionName();
                    } else if (AppConstants.TAMIL.equals(language)) {
                        val = ds.getTaDivisionName();
                    }
                    dsDivisionsSelectedList.put(ds.getId(), val);

                    if (isPLCUSer()) {
                        province = dsDivisionSelectedList.iterator().next().getDistrict().getProvince().getId();
                    }

//            id = userDAO.getUserByUserName(updateUser.getUsername()).getRole().getId();
//             if (id.equals(AppConstants.ORLM_USER_ROLE) || id.equals(AppConstants.ORDS_USER_ROLE) || id.equals(AppConstants.LO_USER_ROLE)) {
//               dsDivisionList.add(ds);
//                 logger.debug("id = {}, dsDivision ", username);
//            }
                }
            }
        }
        logger.debug("size of list :{}", dsDivisionsSelectedList.size());
    }

    private void setDistrictsSelectedList() {
        Set<District> districtSelectedList = userDAO.getUserByUserName(userId).getDistricts();

        if (districtSelectedList != null && districtSelectedList.size() != 0) {
            if (isBranchUser()) {

                district = districtSelectedList.iterator().next().getId();
                province = districtDAO.getDistrictById(district).getProvince().getId();
                branch = userDAO.getUserByUserName(userId).getBranch().getId();

                // districtList = districtDAO.getAllDistrictNamesByProvinceId(province, language, user); //western province

                assignedDistricts = new int[districtSelectedList.size()];
                int i = 0;
                for (District d : districtSelectedList) {
                    assignedDistricts[i] = d.getId();
                    i++;
                }
                dsDivisionList = dsDivisionDAO.getDSDivisionNamesByDistrictId(district, language, user);
            }
        } else if (isBranchHead()) {
            branch = userDAO.getUserByUserName(userId).getBranch().getId();
        }
        logger.debug("size of list :{}", dsDivisionsSelectedList.size());
    }

    private void setUserRolesSelectedList() {
        Set<Role> roleList = userDAO.getUserByUserName(userId).getRoles();
        userRolesSelectedList = new HashMap<String, String>();
        for (Role role : roleList) {
            String val = role.getId();
            userRolesSelectedList.put(role.getId(), val);
        }
        logger.debug("size of list :{}", dsDivisionsSelectedList.size());
    }

    private Set<DSDivision> populateDSDivisions() {
        Set<DSDivision> dsDivisionList = new HashSet<DSDivision>();

        if (isDSUser()) {
            if (dsDivision > 0) {
                dsDivisionList.add(dsDivisionDAO.getDSDivisionByPK(dsDivision));
            } else {
                addActionError("Please Select DS Division");
                return dsDivisionList;
            }
            logger.debug("\n\n\n\nORLM or ORDS or LO:{}", dsDivision);
            return dsDivisionList;
        } else if (isPLCUSer()) {
            //get ds division list by Province Id
            //Western province id = 1
            logger.debug("PLC user province{}", province);
            return dsDivisionDAO.getDSDivisionListByProvinceId(province);

//            if (dsDivisionsSelected != null) {
//                for (int ds : dsDivisionsSelected) {
//                    dsDivisionList.add(dsDivisionDAO.getDSDivisionByPK(ds));
//                }
//                logger.debug("User is not ORLM or ORDS:{}", dsDivisionsSelected.length);
//            }
        } else if (AppConstants.ORIP_USER_ROLE.equals(roleId)) {
            dsDivisionList.add(dsDivisionDAO.getDSDivisionByPK(AppConstants.ORIP_DEFAULT_DS_ID));
            return dsDivisionList;
        } else { //admin, ORMOI, LCG, ORLP
            //todo: make ds list null, means remove existing DS on edit mode
            return dsDivisionList; //empty list
        }
    }

    private Set<District> populateDistricts() {
        Set<District> districtList = new HashSet<District>();

      /*  if (isBranchUser()) {
            if (district > 0) {
                districtList.add(districtDAO.getDistrictById(district));
            } else {
                addActionError("Please Select District");
                return districtList;
            }
            return districtList;

        } else {
            return districtList; //empty list
        }*/
        if (isBranchUser()) {
            if (assignedDistricts.length > 0) {
                for (int i : assignedDistricts) {
                    districtList.add(districtDAO.getDistrictById(i));
                }
            } else {
                addActionError("Please Select District");
                return districtList;
            }
            return districtList;

        } else {
            return districtList; //empty list
        }
    }

    private Branch populateBranch() {
        Branch selectBranch = null;
        logger.debug("\n\nbranch {}", branch);
        if (isBranchUser() || isBranchHead()) {
            if (branch > 0) {
                selectBranch = branchDAO.getBranchById(branch);
                return selectBranch;
            } else {
                addActionError("Please Select Branch");
                return selectBranch;
            }

        } else {
            return selectBranch; //empty list
        }
    }


    /*private void populateUpdateUsersList() {
        //todo: refactore this code
        logger.debug("Populate Update User Lists [user name: {}]", getUser().getUsername());

        roleListByRoleId = roleDAO.getRoleList();
        roleSet = roleListByRoleId.keySet();
        //roleSet.remove("SLC");
        username = user.getUsername();
        userList = userDAO.getAllUsers();//todo: omit default users admin, orlp, lcg
        state = User.State.values();
        stateId = User.State.ACTIVE;
        prefLanguage = user.getPrefLanguage();
        provinceList = provinceDAO.getProvinceList();
        districtList = districtDAO.getAllDistrictNamesByProvinceId(1, language, user);
        dsDivisionList = dsDivisionDAO.getDSDivisionNamesByDistrictId(1, language, user);
        //dsDivisionList = dsDivisionDAO.getDSDivisionNamesByDistrictId(1, language, user);
        dsDivisionsSelectedList = new HashMap<Integer, String>();
        userRolesSelectedList = new HashMap<String, String>();
    }*/

    public String searchUsersByRole() {

        logger.debug("searchUsersByRole user:{}", user.getUsername());

        searchMode = 1;

        try {
            logger.debug("searchUsersByRole RoleID:{}", roleId);
            //roleListByRoleId = roleDAO.getRoleList();
            //roleSet = roleListByRoleId.keySet();
            //roleSet.remove("SLC");
            username = user.getUsername();

            populateBasicLists();

            if (roleId.equals("0")) {

                if (AppConstants.PA_USER_ROLE.equals(user.getRole().getId())) {
                    logger.debug("searchUsersByRole userProvinceId:{}", userProvinceId);
                    userList = userDAO.getAllUsersByPA(userProvinceId, user);
                } else {
                    userList = userDAO.getAllUsers();
                }

            } else {

                if (AppConstants.PA_USER_ROLE.equals(user.getRole().getId())) {
                    logger.debug("searchUsersByRole userProvinceId:{}", userProvinceId);
                    logger.debug("User Role ID : {}", user.getRole().getId());
                    logger.debug("Selected Role ID : {}", roleId);

                    if (AppConstants.SLC_USER_ROLE.equals(roleId)) {
                        slcLandApplicationsList = landApplicationDAO.getApplicationsByProvinceForSlcUsers(userProvinceId);

                        if (slcLandApplicationsList != null) {
                            for (LandApplication l : slcLandApplicationsList) {
                                User u = l.getHolder().getSlcUser();
                                if (u != null) {
                                    userList.add(u);
                                }
                            }
                        }
                    } else {
                        userList = userDAO.getUsersByRoleProvince(roleId, userProvinceId, user);
                    }
                } else {
                    userList = userDAO.getUsersByRole(roleId);
                }
            }

            /*state = User.State.values();
            stateId = User.State.ACTIVE;
            prefLanguage = user.getPrefLanguage();
            provinceList = provinceDAO.getProvinceList();
            districtList = districtDAO.getAllDistrictNamesByProvinceId(1, language, user);
            dsDivisionList = dsDivisionDAO.getDSDivisionNamesByDistrictId(1, language, user);
            //dsDivisionList = dsDivisionDAO.getDSDivisionNamesByDistrictId(1, language, user);
            dsDivisionsSelectedList = new HashMap<Integer, String>();
            userRolesSelectedList = new HashMap<String, String>();*/


            return SUCCESS;

        } catch (Exception e) {
            e.printStackTrace();
            return ERROR;
        }

    }


    private Set<Role> populateUserRoles() {
        Set<Role> roleList = new HashSet<Role>();
        if (userRolesSelected != null) {
            for (String roleId : userRolesSelected) {
                roleList.add(roleDAO.getRole(roleId));
            }
        }
        return roleList;
    }

    private String getRandomPassword(int length) {
        StringBuffer buffer = new StringBuffer();
        Random random = new Random();
        char[] charArray = new char[]{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
                'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
                'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
                'W', 'X', 'Y', 'Z', '0', '1', '2', '3', '4', '5', '6', '7',
                '8', '9'};
        for (int i = 0; i < length; i++) {
            buffer.append(charArray[random.nextInt(charArray.length)]);
        }
        return buffer.toString();
    }

    private boolean sendMail(String receiverEmail, String userName, String password) {

        String msg = "Your User Name is      : " + userName +
                "\nGenerated Password is : " + password +
                "\nPlease log and change your password" +
                "\n\n Site Url : " + AppConstants.APPLICATION_URL;
        boolean mailSent = true;


        mailSent = mailSenderService.sendMail("from@no-spam.com", receiverEmail, "User Registration" +
                "", msg);

        return mailSent;


    }

    private int getRandomInteger() {
        int START = 8;
        int END = 12;
        Random random = new Random();
        if (START > END) {
            throw new IllegalArgumentException("Start cannot exceed End.");
        }
        long range = (long) END - (long) START + 1;
        long fraction = (long) (range * random.nextDouble());
        return (int) (fraction + START);
    }


    public User getRegisterUser() {
        return registerUser;
    }

    public void setRegisterUser(User registerUser) {
        this.registerUser = registerUser;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getRetypePassword() {
        return retypePassword;
    }

    public void setRetypePassword(String retypePassword) {
        this.retypePassword = retypePassword;
    }

    public Map<String, String> getRoleListByRoleId() {
        return roleListByRoleId;
    }

    public void setRoleListByRoleId(Map<String, String> roleListByRoleId) {
        this.roleListByRoleId = roleListByRoleId;
    }

    public Set<String> getRoleSet() {
        return roleSet;
    }

    public void setRoleSet(Set<String> roleSet) {
        this.roleSet = roleSet;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getNewPassword() {
        return newPassword;
    }

    public void setNewPassword(String newPassword) {
        this.newPassword = newPassword;
    }

    public List<User> getUserList() {
        return userList;
    }

    public void setUserList(List<User> userList) {
        this.userList = userList;
    }

    public User.State[] getState() {
        return state;
    }

    public void setState(User.State[] state) {
        this.state = state;
    }

    public User.State getStateId() {
        return stateId;
    }

    public void setStateId(User.State stateId) {
        this.stateId = stateId;
    }

    public String getPrefLanguage() {
        return prefLanguage;
    }

    public void setPrefLanguage(String prefLanguage) {
        this.prefLanguage = prefLanguage;
    }

    public Map<Integer, String> getDistrictList() {
        return districtList;
    }

    public void setDistrictList(Map<Integer, String> districtList) {
        this.districtList = districtList;
    }

    public Map<Integer, String> getDsDivisionList() {
        return dsDivisionList;
    }

    public void setDsDivisionList(Map<Integer, String> dsDivisionList) {
        this.dsDivisionList = dsDivisionList;
    }

    public Map<Integer, String> getDsDivisionsSelectedList() {
        return dsDivisionsSelectedList;
    }

    public void setDsDivisionsSelectedList(Map<Integer, String> dsDivisionsSelectedList) {
        this.dsDivisionsSelectedList = dsDivisionsSelectedList;
    }

    public int[] getDsDivisionsSelected() {
        return dsDivisionsSelected;
    }

    public void setDsDivisionsSelected(int[] dsDivisionsSelected) {
        this.dsDivisionsSelected = dsDivisionsSelected;
    }

    public String getUserId() {
        return userId;
    }

    public void setUserId(String userId) {
        this.userId = userId;
    }

    public int getEditMode() {
        return editMode;
    }

    public void setEditMode(int editMode) {
        this.editMode = editMode;
    }

    public Map<String, String> getUserRolesSelectedList() {
        return userRolesSelectedList;
    }

    public void setUserRolesSelectedList(Map<String, String> userRolesSelectedList) {
        this.userRolesSelectedList = userRolesSelectedList;
    }

    public String[] getUserRolesSelected() {
        return userRolesSelected;
    }

    public void setUserRolesSelected(String[] userRolesSelected) {
        this.userRolesSelected = userRolesSelected;
    }

    public int getDsDivision() {
        return dsDivision;
    }

    public void setDsDivision(int dsDivision) {
        this.dsDivision = dsDivision;
    }

    public void setDistrict(int district) {
        this.district = district;
    }

    public int getDistrict() {
        return district;
    }

    public String getRoleId() {
        return roleId;
    }

    public void setRoleId(String roleId) {
        this.roleId = roleId;
    }

    public Map<Integer, String> getProvinceList() {
        return provinceList;
    }

    public void setProvinceList(Map<Integer, String> provinceList) {
        this.provinceList = provinceList;
    }

    public int getProvince() {
        return province;
    }

    public void setProvince(int province) {
        this.province = province;
    }

    public List<LandApplication> getSlcLandApplicationsList() {
        return slcLandApplicationsList;
    }

    public void setSlcLandApplicationsList(List<LandApplication> slcLandApplicationsList) {
        this.slcLandApplicationsList = slcLandApplicationsList;
    }

    public int getSearchMode() {
        return searchMode;
    }

    public void setSearchMode(int searchMode) {
        this.searchMode = searchMode;
    }

    public Map<Integer, String> getBranchList() {
        return branchList;
    }

    public void setBranchList(Map<Integer, String> branchList) {
        this.branchList = branchList;
    }

    public int getBranch() {
        return branch;
    }

    public void setBranch(int branch) {
        this.branch = branch;
    }

    public int[] getAssignedDistricts() {
        return assignedDistricts;
    }

    public void setAssignedDistricts(int[] assignedDistricts) {
        this.assignedDistricts = assignedDistricts;
    }
}

